package com.tsj.model.utils;

import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.openxml4j.opc.OPCPackage;
import org.apache.poi.openxml4j.opc.PackagePart;
import org.apache.poi.openxml4j.opc.PackageRelationship;
import org.apache.poi.openxml4j.opc.TargetMode;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

import java.io.*;
import java.net.URL;
import java.util.Iterator;
import java.util.List;

public class ExcelAttachmentExtractor {

    public static void main(String[] args) {
        String excelUrl = "http://192.168.0.63:9000/digital-middle-platform/files/resource/resource/68fb19ece4b0c594140f49bc.xlsx"; // Excel文件的URL
        String saveDir = "S:/"; // 本地保存目录

        try {
            // 1. 从URL下载Excel文件到输入流
            InputStream excelInputStream = downloadExcelFromUrl(excelUrl);

            // 2. 解析Excel文件，提取附件并保存
            extractAndSaveAttachments(excelInputStream, saveDir);

            System.out.println("附件提取完成，保存路径：" + saveDir);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 从URL下载Excel文件，返回输入流
     */
    private static InputStream downloadExcelFromUrl(String url) throws Exception {
        URL url2 = new URL(url);
        return  url2.openStream();
    }

    /**
     * 提取Excel中的附件并保存到本地目录
     */
    private static void extractAndSaveAttachments(InputStream excelInputStream, String saveDir) throws Exception {
        // 创建保存目录（不存在则创建）
        File dir = new File(saveDir);
        if (!dir.exists()) {
            dir.mkdirs();
        }

        // 使用POI解析Excel（xlsx格式）
        try (OPCPackage opcPackage = OPCPackage.open(excelInputStream);
             XSSFWorkbook workbook = new XSSFWorkbook(opcPackage)) {

            // 获取所有嵌入式附件（PackagePart）
            List<PackagePart> parts = opcPackage.getParts();
            for (PackagePart part : parts) {
                // 过滤出附件（根据内容类型判断，非Excel本身的核心部分）
                String contentType = part.getContentType();
                if (isAttachmentContentType(contentType)) {
                    // 获取附件文件名（优先从关系中获取，否则用PartName）
                    String fileName = getAttachmentFileName(part);
                    if (fileName == null || fileName.isEmpty()) {
                        fileName = "attachment_" + System.currentTimeMillis(); // 默认文件名
                    }

                    // 读取附件内容并保存到本地
                    try (InputStream partInputStream = part.getInputStream();
                         FileOutputStream fos = new FileOutputStream(saveDir + fileName)) {

                        byte[] buffer = new byte[1024];
                        int bytesRead;
                        while ((bytesRead = partInputStream.read(buffer)) != -1) {
                            fos.write(buffer, 0, bytesRead);
                        }
                        System.out.println("已保存附件：" + fileName);
                    }
                }
            }
        }
    }

    /**
     * 判断是否为附件类型的内容（排除Excel自身的XML部分）
     */
    private static boolean isAttachmentContentType(String contentType) {
        // 常见附件类型（可根据需求扩展）
        return !(contentType.startsWith("application/vnd.openxmlformats-officedocument")
                && (contentType.contains("sheet") || contentType.contains("document") || contentType.contains("xml")));
    }

    /**
     * 获取附件的文件名
     */
    private static String getAttachmentFileName(PackagePart part) throws InvalidFormatException {
        // 遍历所有关系（POI 5.x中getRelationships()返回Iterable，需手动转为流或迭代）
        Iterable<PackageRelationship> relationships = part.getRelationships();
        if (relationships != null) {
            Iterator<PackageRelationship> iterator = relationships.iterator();
            while (iterator.hasNext()) {
                PackageRelationship rel = iterator.next();
                // 检查目标模式是否为内部（INTERNAL）
                if (rel.getTargetMode() == TargetMode.INTERNAL) {
                    // 获取目标Part的名称，提取文件名
                    String targetPartName = rel.getTargetMode().name();
                    return targetPartName.substring(targetPartName.lastIndexOf('/') + 1);
                }
            }
        }
        // 若关系中无文件名，从当前Part的名称中提取
        String partName = part.getPartName().getName();
        return partName.substring(partName.lastIndexOf('/') + 1);
    }
}